﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using PitLib;

namespace SEMPit
{
    /// <summary>
    /// Enum for graph line visibility
    /// </summary>
    public enum Visibility
    {
        Amperage,
        Voltage,
        Speed,
        Distance,
        Wattage,
        Temperature
    };

    public partial class FormMainPit : Form
    {

        private Car _car;
        private DataStorage _dataLog;
        private DataStorage _errorLog;
        private bool _isLoggingError;
        private bool _isLoggingData;

        /// <summary>
        /// Constructor
        /// </summary>
        public FormMainPit()
        {
            InitializeComponent();

            this.Location = new Point(0, 0);
            this.Bounds = Screen.PrimaryScreen.Bounds;

            _car = new Car();
            _car.EventNewData += _car_EventNewData;
            _car.ExceptionOccured += _car_ExceptionOccured;
            
            _isLoggingError = false;
            _isLoggingData = false;

            getComPorts();
            initGUI();
        }

        void _car_ExceptionOccured(string message)
        {
            if (_isLoggingError)
            {
                _errorLog.Log(message);
            }
        }

        #region (Help) methods

        private void initGUI()
        {
            //Simple way to convert an enum to a string array

            var myList = Enum.GetValues(typeof(Visibility)).Cast<Visibility>().Select(v => v.ToString()).ToArray();
            checkedListBox1.Items.AddRange(myList);

            if (comboBoxXBee.Items.Count > 0)
            {
                buttonStart.Enabled = true;
            }
        }

        private void getComPorts()
        {
            try
            {
                foreach (var portName in SerialPort.GetPortNames())
                {
                    comboBoxXBee.Items.Add(portName);
                }

                if (comboBoxXBee.Items.Count != 0)
                {
                    comboBoxXBee.SelectedIndex = 0; ;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        #region Events

        private void _car_EventNewData(DateTime dateTime, double amperage, double distance, int section, double speed, double voltage, double wattage, double temperature)
        {
            Graph.updateGraph(amperage, distance, speed, voltage, wattage, temperature);
            if (_isLoggingData)
            {
                string[] data = new string[7];
                data[0] = amperage.ToString();
                data[1] = distance.ToString();
                data[2] = section.ToString();
                data[3] = speed.ToString();
                data[4] = voltage.ToString();
                data[5] = wattage.ToString();
                data[6] = temperature.ToString();
                _dataLog.Log(data);
            }
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            bool isOpen = _car.Init(comboBoxXBee.Text);
            if (isOpen)
            {
                labelCOMStatus.Text = "Status: Open";
                timerAlive.Enabled = true;
                buttonStop.Enabled = true;
                buttonStart.Enabled = false;
            }
            else
            {
                labelCOMStatus.Text = "Status: Closed";
            }
        }

        /// <summary>
        /// [EVENT] Custom: change visibility of the checked sender
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void myCheckChange(object sender, ItemCheckEventArgs e)
        {
            var checkedListBox = (CheckedListBox)sender;
            var checkedItemText = checkedListBox.Items[e.Index].ToString();

            if (e.NewValue == CheckState.Unchecked)
            {
                Graph.LineVisibility(checkedItemText, true);
            }

            else
            {
                Graph.LineVisibility(checkedItemText, false);
            }
        }

        /// <summary>
        /// Send alive message
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerAlive_Tick(object sender, EventArgs e)
        {
            _car.SendAlive();
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            bool isOpen = _car.ClosePort();
            if (isOpen)
            {
                labelCOMStatus.Text = "Status: Open";
            }
            else
            {
                labelCOMStatus.Text = "Status: Closed";
                buttonStop.Enabled = false;
                buttonStart.Enabled = true;
            }
        }

        private void FormMainPit_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (DialogResult.Yes == MessageBox.Show("Are you sure you want to close the application?", "Confirm", MessageBoxButtons.YesNo, MessageBoxIcon.Question))
            {
                _car.ClosePort();
                if (_errorLog != null)
                {
                    _errorLog.StopLogging();
                }

                if (_dataLog != null)
                {
                    _dataLog.StopLogging();
                }
            }
            else
            {
                e.Cancel = true;
            }
        }

        #endregion

        private void checkedListBox1_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                contextMenuLineVisibility.Show(checkedListBox1, e.Location);
            }
        }

        private void toolStripItemCheckAll_Click(object sender, EventArgs e)
        {
            // Loop through and set all to checked.
            for (int x = 0; x < checkedListBox1.Items.Count; x++)
            {
                checkedListBox1.SetItemChecked(x, true);
            }
        }

        private void toolStripItemUncheckAll_Click(object sender, EventArgs e)
        {
            // Loop through and set all to unchecked.
            for (int x = 0; x < checkedListBox1.Items.Count; x++)
            {
                checkedListBox1.SetItemChecked(x, false);
            }
        }

        private void timerCheckCOM_Tick(object sender, EventArgs e)
        {
            if (_car.GetCOMStatus())
            {
                labelCOMStatus.Text = "Status: Open";
                buttonStop.Enabled = true;
                buttonStart.Enabled = false;
            }
            else
            {
                labelCOMStatus.Text = "Status: Closed";
                buttonStop.Enabled = false;
                buttonStart.Enabled = true;
            }
        }

        private void buttonSelectErrorLogFile_Click(object sender, EventArgs e)
        {
            SaveFileDialog SaveFileDialog = new SaveFileDialog();
            SaveFileDialog.Filter = "TXT file (*.txt)|*.txt";
            if (DialogResult.OK == SaveFileDialog.ShowDialog())
            {
                _errorLog = new DataStorage(SaveFileDialog.FileName);
                _errorLog.StartLoggingError();
                _isLoggingError = true;
            }
        }

        private void buttonSelectLogFile_Click(object sender, EventArgs e)
        {
            SaveFileDialog SaveFileDialog = new SaveFileDialog();
            SaveFileDialog.Filter = "TXT file (*.txt)|*.txt";
            if (DialogResult.OK == SaveFileDialog.ShowDialog())
            {
                _dataLog = new DataStorage(SaveFileDialog.FileName);
                _dataLog.StartLogging();
                _isLoggingData = true;
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}